#pragma once
#ifndef ENGINE_H
#define ENGINE_H
#include "mainwindow.h"
#include "Chess.h"
#include "hashmanger.h"
#include <future>
class MainWindow;

class Engine : public QObject
{
    Q_OBJECT
public:
    Engine() = delete;
    Engine(MainWindow *w);
    void best_step(int player);
    bool if_use_hash = false;    //用于控制是否使用哈希表计算
    bool if_update_hash = false;
    bool if_load_after_cal = true;
    bool limit_time = false;
    int max_consider_time = 60; //最大思考时间，以秒为单位
    bool computer_remote = false; //用于得知电脑是否后手
    char now_search_mode = 1;   //用于控制宽度和深度的模式，如果哈希表利用率低于0.3切换
    //控制棋子走了多少时切换评估函数
    //先手参数
    //Stage 1:
    const int stage1 = 9;
    const int queen_ratio1 = 0,king_ratio1 = 1,dim_ratio1 = 1;
    //Stage 2:
    const int stage2 = 15;
    const int queen_ratio2 = 1, king_ratio2 = 4,dim_ratio2 = 3;
    //Stage 3:
    const int stage3 = 20;
    const int queen_ratio3 = 3, king_ratio3 = 4,dim_ratio3 = 0;
    //Stage 4：
    const int stage4 = 30;
    const int queen_ratio4 = 4, king_ratio4 = 3,dim_ratio4 = 0;
    //Stage 5:
    const int stage5 = 40;
    const int queen_ratio5 = 3, king_ratio5 = 2,dim_ratio5 = 0;
    //Stage 6:
    const int stage6 = 60;
    const int queen_ratio6 = 3, king_ratio6 = 2,dim_ratio6 = 0;
    //Stage 8:
    const int stage7 = 75;
    const int queen_ratio7 = 3, king_ratio7 = 2,dim_ratio7 = 0;
    //Stage 7: 90~end
    const int queen_ratio8 = 2, king_ratio8 = 1,dim_ratio8 = 0;

    //后手参数
    //Stage 1: 0~20
    const int stage1_2 = 9;
    const int queen_ratio1_2 = 0,king_ratio1_2 = 1,dim_ratio1_2 = 1;
    //Stage 2: 20~80
    const int stage2_2 = 14;
    const int queen_ratio2_2 = 1, king_ratio2_2 = 2,dim_ratio2_2 = 0;
    //Stage 3:
    const int stage3_2 = 18;
    const int queen_ratio3_2 = 2, king_ratio3_2 = 3,dim_ratio3_2 = 0;
    //Stage 4：
    const int stage4_2 = 25;
    const int queen_ratio4_2 = 3, king_ratio4_2 = 4,dim_ratio4_2 = 0;
    //Stage 5:
    const int stage5_2 = 30;
    const int queen_ratio5_2 = 1, king_ratio5_2 = 1,dim_ratio5_2 = 0;
    //Stage 6:
    const int stage6_2 = 35;
    const int queen_ratio6_2 = 4, king_ratio6_2 = 3,dim_ratio6_2 = 0;
    //Stage 8:
    const int stage7_2 = 75;
    const int queen_ratio7_2 = 3, king_ratio7_2 = 2,dim_ratio7_2 = 0;
    //Stage 7: 90~end
    const int queen_ratio8_2 = 2, king_ratio8_2 = 1,dim_ratio8_2 = 0;

    char krt,qrt,drt; //用于记录当前步数下的评估函数比例
    static const int FW0 = 150,DEPTH0 = 4,WIDTH0 = 150,S1 = 30;
    static const int FW1 = 80,DEPTH1 = 5,WIDTH1 = 80,S2 = 55;
    static const int FW2 = 80,DEPTH2 = 5,WIDTH2 = 80,S3 = 55;
    static const int FW3 = 40,DEPTH3 = 6,WIDTH3 = 40,S4 = 70;
    static const int FW4 = 15, DEPTH4 = 8,WIDTH4 = 15,S5 = 80;
    static const int FW5 = 15, DEPTH5 = 9,WIDTH5 = 15,S6 = 90;
    static const int FW6 = 10, DEPTH6 = 10,WIDTH6 = 10,S7 = 90;
    static const int FW7 = 5, DEPTH7 = 100,WIDTH7 = 5,S8 = 100;

    static const int FW0_2 = 150,DEPTH0_2 = 4,WIDTH0_2 =150,S1_2 = 18;
    static const int FW1_2 = 150,DEPTH1_2 = 4,WIDTH1_2 = 150,S2_2 = 30;
    static const int FW2_2 = 80,DEPTH2_2 = 5,WIDTH2_2 = 80,S3_2 = 55;
    static const int FW3_2 = 40,DEPTH3_2= 6,WIDTH3_2 = 40,S4_2 = 70;
    static const int FW4_2 = 15, DEPTH4_2 = 7,WIDTH4_2 = 15,S5_2 = 70;
    static const int FW5_2 = 10, DEPTH5_2 = 9,WIDTH5_2 = 10,S6_2 = 80;
    static const int FW6_2 = 10, DEPTH6_2 = 10,WIDTH6_2 = 10,S7_2 = 90;
    static const int FW7_2 = 5, DEPTH7_2 = 100,WIDTH7_2 = 5,S8_2 = 100;
    void reset_hash(bool is_first);
    char king_move(const Cb_with_num &chessborad);
    char queen_move(const Cb_with_num &cb);
private:
    int thread_count = 0;
    Step best;  //用于保存最好走法
    bool has_return = false; //用于查看是否计算完成
    class std::thread *t;
    bool is_killed = false;
    Cb_with_num *cb;
    bool* player;
    HashManger *hash_manger;
    class std::thread *load_thread[3];

    //寻找合法的走子位置并堆入vector,实际为Queen的一步走法
    /*
     *两个函数的不同之处在于，find_next_pos接受一个棋子并返回其走法，实际就是一个棋子的queen走法
     * find_sum_step一次返回当前所有棋子的走法
    */
    void find_next_pos(const Chess& c,int player,std::vector <Step>& futurechess,int * chessborad);
    void find_sum_step(int player,std::vector <Step> &nextstep,Cb_with_num &chessborad);
    //queen的一步走法，find_next_pos的带标记版
    void find_queen_pos(int c,int player,std::queue <int>& futurechess,int res[],int dis,int &blackoccupy,int &whiteoccupy);
    //king的一步走法，解释同find_next_pos
    void find_king_pos(int c,int player,std::queue <int>& futurechess,int res[],int dis,int &blackoccupy,int &whiteoccupy);
    //用于改变虚拟棋盘的棋子以及棋盘
    void temp_set(const Step &s,int player,Cb_with_num &cb);
    //虚拟棋盘回溯
    void temp_back(const Step &s,int player,Cb_with_num &cb);
    int ef(const Step &s,int player,Cb_with_num &cb);
    int dim(Cb_with_num &cb);
    //判断胜利
    int winner(const Cb_with_num &cb);
    Score_struct find_score(Cb_with_num &cb);
    //以下博弈树相关
    int get_depth(int chess_num);
    int get_width(int chess_num);
    int get_FD(int chess_num);
    int dfs(const Step &s,int player,int a,int b,Cb_with_num &cb,int depth = 2);
    char get_krt(int chess_num);
    char get_qrt(int chess_num);
    char get_drt(int chess_num);
    ~Engine(){}
signals:
    void notyify_ui(Step s);
    void continue_cal();
    void load_begin();
    void finish_load0();
    void finish_load1();
    void finish_load2();
private slots:
    void stop(){
        has_return = true;
    }
};
#endif
